package xj.model.uml;

import static xj.model.uml.UMLModelConstants.ATTR_AGGREGATION;
import static xj.model.uml.UMLModelConstants.ATTR_CHANGEABILITY;
import static xj.model.uml.UMLModelConstants.ATTR_MULTIPLICITY;
import static xj.model.uml.UMLModelConstants.ATTR_NAVIGABILITY;
import static xj.model.uml.UMLModelConstants.ATTR_ORDERED;
import static xj.model.uml.UMLModelConstants.ATTR_ROLENAME;
import static xj.model.uml.UMLModelConstants.ATTR_UNIQUE;

public class UMLAssociationEnd extends BasicModelElement {

  public enum AggregationKind {
    None, Shared, Composite
  };

  public UMLAssociationEnd() {
    this(null, null, null);
  }

  public UMLAssociationEnd(String role, Multiplicity multiplicity) {
    this(role, multiplicity, null);
  }

  public UMLAssociationEnd(String role, Multiplicity multiplicity,
			   Navigability navigability) {
    setRole(role);
    setMultiplicity(multiplicity);
    setNavigability(navigability);
    destructable = false;
    preserved = true;
  }

  public String getRoleName() {
    return roleName;
  }

  public void setRoleName(String roleName) {
    this.roleName = roleName;
    setAttribute(ATTR_ROLENAME, roleName);
  }

  public Multiplicity getMultiplicity() {
    return multiplicity;
  }

  public void setMultiplicity(Multiplicity multiplicity) {
    this.multiplicity = multiplicity;
    setAttribute(ATTR_MULTIPLICITY, multiplicity);
  }

  public CollectionType getCollectionType() {
    if (multiplicity == Multiplicity.OneToMany || 
	multiplicity == Multiplicity.Many) {
      return CollectionType.toCollectionType(ordered, unique);
    } else {
      return null;
    }
  }

  public void setCollectionType(CollectionType c) {
    if (c != null) {
      setOrdered(CollectionType.isOrdered(c));
      setUnique(CollectionType.isUnique(c));
    }
  }

  public Navigability getNavigability() {
    return navigability;
  }

  public void setNavigability(Navigability n) {
    navigability = n;
    setAttribute(ATTR_NAVIGABILITY, n);
  }

  public Changeability getChangeability() {
    return changeability;
  }

  public void setChangeability(Changeability changeability) {
    this.changeability = changeability;
    setAttribute(ATTR_CHANGEABILITY, changeability);
  }

  public AggregationKind getAggregation() {
    return aggregation;
  }

  public void setAggregation(AggregationKind a) {
    aggregation = a;
    setAttribute(ATTR_AGGREGATION, a);
  }

  public boolean isOrdered() {
    return ordered;
  }

  public void setOrdered(boolean n) {
    ordered = n;
    setAttribute(ATTR_ORDERED, n);
  }

  public boolean isUnique() {
    return unique;
  }

  public void setUnique(boolean n) {
    unique = n;
    setAttribute(ATTR_UNIQUE, n);
  }

  @Override
  public String toString() {
    return "UMLAssociationEnd: role=" + role + " multiplicity=" + multiplicity + 
      " aggregation=" + aggregation + " navigability=" + navigability;
  }

  @Override
  public Object clone() throws CloneNotSupportedException {
    UMLAssociationEnd end = (UMLAssociationEnd) super.clone();
    end.setRole(roleName);
    end.setMultiplicity(multiplicity);
    end.setAggregation(aggregation);
    end.setNavigability(navigability);
    end.setChangeability(changeability);
    end.setOrdered(ordered);
    end.setUnique(unique);
    return end;
  }

  protected String roleName = null;

  protected Multiplicity multiplicity = null;

  protected Changeability changeability = Changeability.Changeable;

  protected AggregationKind aggregation = null;

  protected Navigability navigability = Navigability.Default;

  protected boolean ordered = false;

  protected boolean unique = true;

}
